package com.apes.fn.scm.prepare.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.scm.advancePayment.AdvancePayment;
import com.apes.fn.scm.advancePayment.AdvancePaymentMethod;
import com.apes.fn.scm.advancePayment.AdvancePaymentMethodRepository;
import com.apes.fn.scm.advancePayment.AdvancePaymentRepository;
import com.apes.fn.scm.contract.FnContract;
import com.apes.fn.scm.contract.FnContractRepository;
import com.apes.fn.scm.prepare.model.ToPrepare;
import com.apes.fn.scm.prepare.model.ToPrepareDetail;
import com.apes.fn.scm.prepare.repository.ToPrepareRepository;
import com.apes.fn.scm.retailOrder.model.RetailOrder;
import com.apes.fn.scm.retailOrder.model.RetailOrderPayMethod;
import com.apes.fn.scm.retailOrder.repository.RetailOrderRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.LogicalUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.account.ledger.service.LedgerService;
import com.apes.scm.income.model.Income;
import com.apes.scm.income.model.MoneyIncome;
import com.apes.scm.income.repository.MoneyIncomeRepository;
import com.apes.scm.masterdata.enumeration.repository.EnumerationRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 待缴款单
 */
@Service("toPrepareService")
public class ToPrepareService extends DomainService {
    @Autowired
    private ToPrepareRepository toPrepareRepository;
    @Autowired
    private DeptRepository deptRepository;
    @Autowired
    private PartyRoleRepository partyRoleRepository;
    @Autowired
    private RetailOrderRepository retailOrderRepository;
    @Autowired
    private AdvancePaymentRepository repository;
    @Autowired
    private LedgerService ledgerService;
    @Autowired
    private FnContractRepository fnContractRepository;

    /**
     * 创建待缴款单
     *
     * @param request
     * @return
     */
    public ToPrepare create(SimpleRequest request) {
        ToPrepare toPrepare = request.getO(ToPrepare.class);
        return toPrepareRepository.saveAndFlush(toPrepare);
    }

    /**
     * 生成代缴款记录
     *
     * @param request {"orderId":"零售单号", "deptId":"部门编号","sourceBusinessType":"RetailOrder",
     *                "detail":"明细","paymentId":"零售单付款方式编号","money":"金额","paymentType":"收款类型Id"}
     */
    public void storeCashAndSave(SimpleRequest request) {
        JSONObject param = request.getJO();
        Set<ToPrepare> toPrepares = new HashSet<>();
        // 收款方式数据添加
        JSONArray details = param.getJSONArray("details");
        details.forEach(v -> {
            Set<ToPrepareDetail> toPrepareDetails = new HashSet<>();
            ToPrepare toPrepare = new ToPrepare();
            JSONObject temp = (JSONObject) v;
            switch (temp.getString("paymentType")) {
                case "01":
                    toPrepare.setPaymentType(SpringManager.getBean(EnumerationRepository.class).findOne("002035"));
                    break;
                case "09":
                    toPrepare.setPaymentType(SpringManager.getBean(EnumerationRepository.class).findOne("002036"));
                    break;
                default:
                    return;
            }
            //待缴款明细信息
            ToPrepareDetail toPrepareDetail = new ToPrepareDetail();
            toPrepareDetail.setSource(param.getString("orderId"));
            toPrepareDetail.setSourceBusinessType(param.getString("sourceBusinessType"));
            toPrepareDetail.setAmount(temp.getDouble("amount"));
            toPrepareDetails.add(toPrepareDetail);
            toPrepare.setAmount(temp.getDouble("amount"));

            //待缴款信息
            Dept dept = deptRepository.findById(param.getString("deptId"))
                    .orElseThrow(() -> new RuntimeException("根据部门编码没有对应的部门信息，部门编码" + param.getString("deptId")));
            toPrepare.setDept(dept);

            toPrepare.setCompany(dept.getCompany());
            FnContract fnContract = fnContractRepository.findByPartnerAndState(toPrepare.getCompany().getId());
            if(fnContract != null){
                toPrepare.setPlatformCompany(fnContract.getCompany());
            }
            toPrepare.setCollectMoneyDate(new Date());
            toPrepare.setPaymentMoneyDate(new Date());
            toPrepare.setFreezeAmount(toPrepare.getAmount());
            toPrepare.setToPrepareDetails(toPrepareDetails);
            toPrepare.setVersion(1);
            List<FnContract> fnContracts = SpringManager.getBean(FnContractRepository.class)
                    .findAll(JpaDsl.toCriteriaByEq("partner.id", toPrepare.getCompany().getId(), "state", "approve"));
            if(fnContracts.size() > 0){
                toPrepare.setFnContract(fnContracts.get(0));
            }
            toPrepareLedger(toPrepareRepository.saveAndFlush(toPrepare));
        });
    }

    private void toPrepareLedger(ToPrepare toPrepare) {
        if(Objects.isNull(toPrepare.getFnContract())) return;
        ledgerService.charge(toPrepare.getFnContract().getCompany(), SpringManager.getBean(DeptRepository.class)
                        .findByPartyRoleAndDeptType(toPrepare.getFnContract().getCompany().getId(), "000007"), toPrepare.getFnContract().getPartner(), "IM_OWN",
                "AM_PURCHASE", toPrepare.getId(), "ToPrepare",
                new Date(), "current_unsettled", toPrepare.getAmount());
    }

    /**
     * 订金单生成待缴款单
     * @param request
     */
    private void test(SimpleRequest request) {
        AdvancePayment advancePayment = repository.getOne(request.get("id"));
        List<AdvancePaymentMethod> advancePaymentMethodList = advancePayment.getPaymentMethodSet().stream()
                .filter(advancePaymentMethod -> "09".equals(advancePaymentMethod.getPaymentMethodType().getId()) &&
                        !"C0005998".equals(advancePaymentMethod.getCustomer().getId()) &&
                        (advancePayment.getCompany().getParty().getId() != advancePaymentMethod.getCustomer().getParty().getId() ||
                                !"Company".equals(advancePaymentMethod.getCustomer().getRole().getId())))
                .collect(Collectors.toList());
        if (advancePaymentMethodList.size() > 0) {
            List<Map> mapList = advancePaymentMethodList.stream()
                    .map(paymentMethod ->
                            MapUtil.mapper("amount", paymentMethod.getAmount(),
                                    "paymentType", paymentMethod.getPaymentMethodType().getId(),
                                    "paymentId", paymentMethod.getPaymentMethodType().getPaymentType().getId())
                    ).collect(Collectors.toList());
            this.invoke("to.prepare.storeCashAndSave", JSON.toJSONString((MapUtil.mapper("orderId", advancePayment.getId(),
                    "deptId", advancePayment.getDept().getId(), "sourceBusinessType", "AdvancePayment",
                    "details", mapList))));
        }
    }

    /**
     * 零售单生成待缴款单
     * @param request
     */
    private void extracted(SimpleRequest request) {
        RetailOrder retailOrder = retailOrderRepository.getOne(request.get("id"));
        //生成待缴款单,排除定损
        List<RetailOrderPayMethod> retailOrderPayMethodList = retailOrder.getPaymentMethodSet().stream()
                .filter(retailOrderPayMethod -> retailOrderPayMethod.getCustomer() != null)
                .filter(retailOrderPayMethod -> LogicalUtil.notIn(retailOrderPayMethod.getCustomer().getId(), "C0005998", "02532856", "02533043") &&
                        ((partyRoleRepository.findByPartyIdAndRoleId(retailOrderPayMethod.getCustomer().getParty().getId(), "Company") == null ||
                                retailOrder.getCompany().getParty().getId() == retailOrderPayMethod.getCustomer().getParty().getId() ||
                                (!"replacement".equals(retailOrder.getOrderType()) &&
                                        LogicalUtil.notIn(retailOrderPayMethod.getCustomer().getId(), "K1001", "K1003"))) ||
                                ((LogicalUtil.in(retailOrderPayMethod.getCustomer().getId(), "K1001", "K1003")) &&
                                        "replacement".equals(retailOrder.getOrderType()) &&
                                        (retailOrder.getCompany().getParty().getId() == retailOrderPayMethod.getCustomer().getParty().getId() ||
                                                partyRoleRepository.findByPartyIdAndRoleId(retailOrderPayMethod.getCustomer().getParty().getId(), "Company") == null))))
                .collect(Collectors.toList());
        retailOrderPayMethodList.removeIf(Objects::isNull);
        if (retailOrderPayMethodList.isEmpty()) return;
        if (retailOrder.getClaimType() == null) {
            List<Map> mapList = retailOrderPayMethodList.stream()
                    .map(paymentMethod ->
                            MapUtil.mapper("amount", paymentMethod.getAmount(),
                                    "paymentType", paymentMethod.getPaymentMethodType().getId(),
                                    "paymentId", paymentMethod.getPaymentMethodType().getPaymentType().getId())
                    ).collect(Collectors.toList());
            this.invoke("to.prepare.storeCashAndSave", JSON.toJSONString((MapUtil.mapper("orderId", retailOrder.getId(),
                    "deptId", retailOrder.getDept().getId(), "sourceBusinessType", "RetailOrder",
                    "details", mapList))));
        }
    }

    public void privateHomesAndSave(SimpleRequest request) {
        ToPrepare toPrepare = new ToPrepare();
        Set<ToPrepareDetail> toPrepareDetails = new HashSet<>();
        if (!"002037".equals(request.get("payment_type"))) return;
        //子表信息
        ToPrepareDetail toPrepareDetail = new ToPrepareDetail();
        toPrepareDetail.setSource(request.get("lossQuotationId"));
        toPrepareDetail.setSourceBusinessType("LossQuotation");
        toPrepareDetail.setRecord(request.get("lossReceivedItemId"));
        toPrepareDetail.setAmount(request.get("amount"));
        toPrepareDetails.add(toPrepareDetail);
        //主表信息
        toPrepare.setPaymentType(SpringManager.getBean(EnumerationRepository.class).findOne("002037"));
        toPrepare.setAmount(request.get("amount"));
        toPrepare.setFreezeAmount(toPrepare.getAmount());
        Dept dept = deptRepository.findById(request.get("deptId"))
                .orElseThrow(() -> new RuntimeException("根据部门编码没有对应的部门信息，部门编码" + request.get("deptId")));
        toPrepare.setDept(dept);
        toPrepare.setCompany(dept.getCompany());
        toPrepare.setCollectMoneyDate(new Date());
        toPrepare.setPaymentMoneyDate(new Date());
        toPrepare.setVersion(1);
        toPrepare.setToPrepareDetails(toPrepareDetails);
        toPrepareRepository.saveAndFlush(toPrepare);
    }

}
